//package com.qingcloud.common.swagger.config;
//
//import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
//import com.google.common.base.Predicate;
//import com.google.common.base.Predicates;
//import com.google.common.collect.Lists;
//import org.springframework.beans.factory.BeanFactory;
//import org.springframework.beans.factory.BeanFactoryAware;
//import org.springframework.beans.factory.config.ConfigurableBeanFactory;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.Import;
//import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
//import springfox.documentation.builders.ApiInfoBuilder;
//import springfox.documentation.builders.ParameterBuilder;
//import springfox.documentation.builders.PathSelectors;
//import springfox.documentation.builders.RequestHandlerSelectors;
//import springfox.documentation.schema.ModelRef;
//import springfox.documentation.service.ApiInfo;
//import springfox.documentation.service.ApiKey;
//import springfox.documentation.service.AuthorizationScope;
//import springfox.documentation.service.Contact;
//import springfox.documentation.service.Parameter;
//import springfox.documentation.service.SecurityReference;
//import springfox.documentation.spi.DocumentationType;
//import springfox.documentation.spi.service.contexts.SecurityContext;
//import springfox.documentation.spring.web.plugins.Docket;
//import springfox.documentation.swagger2.annotations.EnableSwagger2;
//
//import java.util.ArrayList;
//import java.util.LinkedList;
//import java.util.List;
//import java.util.Objects;
//import java.util.Set;
//import java.util.stream.Collectors;
//
//@Configuration
//@EnableSwagger2
//@EnableKnife4j
//@Import(BeanValidatorPluginsConfiguration.class)
//public class SwaggerAutoConfiguration implements BeanFactoryAware {
//    private static final String AUTH_KEY = "Authorization";
//
//    private BeanFactory beanFactory;
//
//    @Bean
//    @ConditionalOnMissingBean
//    public SwaggerProperties swaggerProperties() {
//        return new SwaggerProperties();
//    }
//
//    @Bean
//    @ConditionalOnMissingBean
//    @ConditionalOnProperty(name = "common.swagger.enabled", matchIfMissing = true)
//    public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
//        ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
//        List<Docket> docketList = new LinkedList<>();
//
//        // 没有分组
//        if (swaggerProperties.getDocket().size() == 0) {
//            final Docket docket = createDocket(swaggerProperties);
//            configurableBeanFactory.registerSingleton("defaultDocket", docket);
//            docketList.add(docket);
//            return docketList;
//        }
//
//        // 分组创建
//        for (String groupName : swaggerProperties.getDocket().keySet()) {
//            SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(groupName);
//
//            ApiInfo apiInfo = new ApiInfoBuilder()
//                    .title(docketInfo.getTitle().isEmpty() ? swaggerProperties.getTitle() : docketInfo.getTitle())
//                    .description(docketInfo.getDescription().isEmpty() ? swaggerProperties.getDescription() : docketInfo.getDescription())
//                    .version(docketInfo.getVersion().isEmpty() ? swaggerProperties.getVersion() : docketInfo.getVersion())
//                    .license(docketInfo.getLicense().isEmpty() ? swaggerProperties.getLicense() : docketInfo.getLicense())
//                    .licenseUrl(docketInfo.getLicenseUrl().isEmpty() ? swaggerProperties.getLicenseUrl() : docketInfo.getLicenseUrl())
//                    .contact(
//                            new Contact(
//                                    docketInfo.getContact().getName().isEmpty() ? swaggerProperties.getContact().getName() : docketInfo.getContact().getName(),
//                                    docketInfo.getContact().getUrl().isEmpty() ? swaggerProperties.getContact().getUrl() : docketInfo.getContact().getUrl(),
//                                    docketInfo.getContact().getEmail().isEmpty() ? swaggerProperties.getContact().getEmail() : docketInfo.getContact().getEmail()
//                            )
//                    )
//                    .termsOfServiceUrl(docketInfo.getTermsOfServiceUrl().isEmpty() ? swaggerProperties.getTermsOfServiceUrl() : docketInfo.getTermsOfServiceUrl())
//                    .build();
//
//            // base-path处理
//            // 当没有配置任何path的时候，解析/**
//            if (docketInfo.getBasePath().isEmpty()) {
//                docketInfo.getBasePath().add("/**");
//            }
//            List<Predicate<String>> basePath = new ArrayList<>(docketInfo.getBasePath().size());
//            for (String path : docketInfo.getBasePath()) {
//                basePath.add(PathSelectors.ant(path));
//            }
//
//            // exclude-path处理
//            List<Predicate<String>> excludePath = new ArrayList<>(docketInfo.getExcludePath().size());
//            for (String path : docketInfo.getExcludePath()) {
//                excludePath.add(PathSelectors.ant(path));
//            }
//
//            Docket docket = new Docket(DocumentationType.SWAGGER_2)
//                    .host(swaggerProperties.getHost())
//                    .apiInfo(apiInfo)
//                    .globalOperationParameters(assemblyGlobalOperationParameters(swaggerProperties.getGlobalOperationParameters(),
//                            docketInfo.getGlobalOperationParameters()))
//                    .groupName(groupName)
//                    .select()
//                    .apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage()))
//                    .paths(
//                            Predicates.and(
//                                    Predicates.not(Predicates.or(excludePath)),
//                                    Predicates.or(basePath)
//                            )
//                    )
//                    .build()
//                    .securitySchemes(securitySchemes())
//                    .securityContexts(securityContexts());
//
//            configurableBeanFactory.registerSingleton(groupName, docket);
//            docketList.add(docket);
//        }
//        return docketList;
//    }
//
//    /**
//     * 创建 Docket对象
//     *
//     * @param swaggerProperties swagger配置
//     * @return Docket
//     */
//    private Docket createDocket(final SwaggerProperties swaggerProperties) {
//        ApiInfo apiInfo = new ApiInfoBuilder()
//                .title(swaggerProperties.getTitle())
//                .description(swaggerProperties.getDescription())
//                .version(swaggerProperties.getVersion())
//                .license(swaggerProperties.getLicense())
//                .licenseUrl(swaggerProperties.getLicenseUrl())
//                .contact(new Contact(swaggerProperties.getContact().getName(),
//                        swaggerProperties.getContact().getUrl(),
//                        swaggerProperties.getContact().getEmail()))
//                .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
//                .build();
//
//        // base-path处理
//        // 当没有配置任何path的时候，解析/**
//        if (swaggerProperties.getBasePath().isEmpty()) {
//            swaggerProperties.getBasePath().add("/**");
//        }
//        List<Predicate<String>> basePath = new ArrayList<>();
//        for (String path : swaggerProperties.getBasePath()) {
//            basePath.add(PathSelectors.ant(path));
//        }
//
//        // exclude-path处理
//        List<Predicate<String>> excludePath = new ArrayList<>();
//        for (String path : swaggerProperties.getExcludePath()) {
//            excludePath.add(PathSelectors.ant(path));
//        }
//
//        return new Docket(DocumentationType.SWAGGER_2)
//                .host(swaggerProperties.getHost())
//                .apiInfo(apiInfo)
//                .globalOperationParameters(buildGlobalOperationParametersFromSwaggerProperties(
//                        swaggerProperties.getGlobalOperationParameters()))
//                .select()
//                .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
//                .paths(
//                        Predicates.and(
//                                Predicates.not(Predicates.or(excludePath)),
//                                Predicates.or(basePath)
//                        )
//                )
//                .build()
//                .securitySchemes(securitySchemes())
//                .securityContexts(securityContexts());
//    }
//
//    @Override
//    public void setBeanFactory(BeanFactory beanFactory) {
//        this.beanFactory = beanFactory;
//    }
//
//    private List<SecurityContext> securityContexts() {
//        List<SecurityContext> contexts = new ArrayList<>(1);
//        SecurityContext securityContext = SecurityContext.builder()
//                .securityReferences(defaultAuth())
//                //.forPaths(PathSelectors.regex("^(?!auth).*$"))
//                .build();
//        contexts.add(securityContext);
//        return contexts;
//    }
//
//    private List<SecurityReference> defaultAuth() {
//        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
//        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
//        authorizationScopes[0] = authorizationScope;
//        List<SecurityReference> references = new ArrayList<>(1);
//        references.add(new SecurityReference(AUTH_KEY, authorizationScopes));
//        return references;
//    }
//
//    private List<ApiKey> securitySchemes() {
//        List<ApiKey> apiKeys = new ArrayList<>(1);
//        ApiKey apiKey = new ApiKey(AUTH_KEY, AUTH_KEY, "header");
//        apiKeys.add(apiKey);
//        return apiKeys;
//    }
//
//    private List<Parameter> buildGlobalOperationParametersFromSwaggerProperties(
//            List<SwaggerProperties.GlobalOperationParameter> globalOperationParameters) {
//        List<Parameter> parameters = Lists.newArrayList();
//
//        if (Objects.isNull(globalOperationParameters)) {
//            return parameters;
//        }
//        for (SwaggerProperties.GlobalOperationParameter globalOperationParameter : globalOperationParameters) {
//            parameters.add(new ParameterBuilder()
//                    .name(globalOperationParameter.getName())
//                    .description(globalOperationParameter.getDescription())
//                    .modelRef(new ModelRef(globalOperationParameter.getModelRef()))
//                    .parameterType(globalOperationParameter.getParameterType())
//                    .required(Boolean.parseBoolean(globalOperationParameter.getRequired()))
//                    .build());
//        }
//        return parameters;
//    }
//
//    /**
//     * 局部参数按照name覆盖局部参数
//     *
//     * @param globalOperationParameters
//     * @param docketOperationParameters
//     * @return
//     */
//    private List<Parameter> assemblyGlobalOperationParameters(
//            List<SwaggerProperties.GlobalOperationParameter> globalOperationParameters,
//            List<SwaggerProperties.GlobalOperationParameter> docketOperationParameters) {
//
//        if (Objects.isNull(docketOperationParameters) || docketOperationParameters.isEmpty()) {
//            return buildGlobalOperationParametersFromSwaggerProperties(globalOperationParameters);
//        }
//
//        Set<String> docketNames = docketOperationParameters.stream()
//                .map(SwaggerProperties.GlobalOperationParameter::getName)
//                .collect(Collectors.toSet());
//
//        List<SwaggerProperties.GlobalOperationParameter> resultOperationParameters = Lists.newArrayList();
//
//        if (Objects.nonNull(globalOperationParameters)) {
//            for (SwaggerProperties.GlobalOperationParameter parameter : globalOperationParameters) {
//                if (!docketNames.contains(parameter.getName())) {
//                    resultOperationParameters.add(parameter);
//                }
//            }
//        }
//
//        resultOperationParameters.addAll(docketOperationParameters);
//        return buildGlobalOperationParametersFromSwaggerProperties(resultOperationParameters);
//    }
//}
